﻿#include "ZFtpPrivate.h"
#include "ZFtpRequestPrivate.h"
#include "ZFtpResponsePrivate.h"
#include <QDebug>

BEGIN_NAMESPACE_ZFTPNS

ZFtpPrivate::ZFtpPrivate(QObject *parent) :
    QObject(parent), q_ptr(NULL)
{
    init();
}

ZFtpPrivate::~ZFtpPrivate()
{
    this->abort();
}

void ZFtpPrivate::setFtpServerTextCodec(const QString &text_codec_name)
{
    m_zftp_config->setTextCodecName(text_codec_name);
}

QString ZFtpPrivate::ftpServerTextCodec()
{
    return m_zftp_config->textCodecName();
}

void ZFtpPrivate::setAutoReconnect(bool reconnect)
{
    m_zftp_config->setAutoReconnect(reconnect);
}

bool ZFtpPrivate::autoReconnect()
{
    return m_zftp_config->autoReconnect();
}

void ZFtpPrivate::connectToHost(QSharedPointer<ConnectToHostRequestPrivate> request,
                                QSharedPointer<ConnectToHostResponsePrivate> response)
{
    // 状态检测
    if (m_ftp && m_ftp->state() != QFtp::Unconnected)
    {
        QString error_string = QStringLiteral("正在建立连接或已建立连接，请稍后重试");
        qWarning() << error_string;

        // 设置任务ID为无效值
        response->setLastErrorString(error_string);
        response->setFtpTaskID(ZFtpResponsePrivate::InvalidTaskID);
        return;
    }

    addTask(request, response);
    tryStartNextTask();
}

void ZFtpPrivate::login(QSharedPointer<LoginRequestPrivate> request,
                        QSharedPointer<LoginResponsePrivate> response)
{
    addTask(request, response);
    tryStartNextTask();
}

void ZFtpPrivate::close(QSharedPointer<CloseFtpRequestPrivate> request,
                        QSharedPointer<CloseFtpResponsePrivate> response)
{
    addTask(request, response);
    tryStartNextTask();
}

void ZFtpPrivate::listDir(QSharedPointer<ListDirRequestPrivate> request,
                          QSharedPointer<ListDirResponsePrivate> response)
{
    addTask(request, response);
    tryStartNextTask();
}

void ZFtpPrivate::mkdir(QSharedPointer<MkDirRequestPrivate> request,
                        QSharedPointer<MkDirResponsePrivate> response)
{
    addTask(request, response);
    tryStartNextTask();
}

void ZFtpPrivate::rmdir(QSharedPointer<RmDirRequestPrivate> request,
                        QSharedPointer<RmDirResponsePrivate> response)
{
    addTask(request, response);
    tryStartNextTask();
}

void ZFtpPrivate::cd(QSharedPointer<CdDirRequestPrivate> request,
                     QSharedPointer<CdDirResponsePrivate> response)
{
    addTask(request, response);
    tryStartNextTask();
}

void ZFtpPrivate::uploadFile(QSharedPointer<UploadFileRequest1Private> request,
                             QSharedPointer<UploadFileResponse1Private> response)
{
    addTask(request, response);
    tryStartNextTask();
}

void ZFtpPrivate::uploadFile(QSharedPointer<UploadFileRequest2Private> request,
                             QSharedPointer<UploadFileResponse2Private> response)
{
    addTask(request, response);
    tryStartNextTask();
}

void ZFtpPrivate::uploadFile(QSharedPointer<UploadFileRequest3Private> request,
                             QSharedPointer<UploadFileResponse3Private> response)
{
    addTask(request, response);
    tryStartNextTask();
}

void ZFtpPrivate::downloadFile(QSharedPointer<DownloadFileRequest1Private> request,
                               QSharedPointer<DownloadFileResponse1Private> response)
{
    addTask(request, response);
    tryStartNextTask();
}

void ZFtpPrivate::downloadFile(QSharedPointer<DownloadFileRequest2Private> request,
                               QSharedPointer<DownloadFileResponse2Private> response)
{
    addTask(request, response);
    tryStartNextTask();
}

void ZFtpPrivate::deleteFile(QSharedPointer<DeleteFileRequestPrivate> request,
                             QSharedPointer<DeleteFileResponsePrivate> response)
{
    addTask(request, response);
    tryStartNextTask();
}

void ZFtpPrivate::renameFile(QSharedPointer<RenameFileRequestPrivate> request,
                             QSharedPointer<RenameFileResponsePrivate> response)
{
    addTask(request, response);
    tryStartNextTask();
}

void ZFtpPrivate::setTransferMode(QFtp::TransferMode mode)
{
    if (m_ftp) m_ftp->setTransferMode(mode);
}

QFtp::State ZFtpPrivate::state() const
{
    QFtp::State state = QFtp::Unconnected;
    if (m_ftp)
    {
        state = m_ftp->state();
    }
    return state;
}

QFtp::Error ZFtpPrivate::error() const
{
    QFtp::Error error = QFtp::NoError;
    if (m_ftp)
    {
        error = m_ftp->error();
    }
    return error;
}

QString ZFtpPrivate::errorString() const
{
    QString error_string;
    if (m_ftp)
    {
        error_string = m_ftp->errorString();
    }
    return error_string;
}

void ZFtpPrivate::abort()
{
    if (m_ftp)
    {
        m_ftp->abort();
        //m_ftp = QSharedPointer<QFtp>();
    }
}

void ZFtpPrivate::init()
{
    m_zftp_config = QSharedPointer<ZFtpConfig>(new ZFtpConfig);

    // 创建QFtp对象
    ensureFtpObjectValid();

    // 建立连接
    createConnects();
}

void ZFtpPrivate::createConnects()
{
    connect(this, SIGNAL(sigNewTaskAdded(QSharedPointer<ZFtpRequestPrivate>,QSharedPointer<ZFtpResponsePrivate>)),
            SLOT(slotNewTaskAdded(QSharedPointer<ZFtpRequestPrivate>,QSharedPointer<ZFtpResponsePrivate>)));
}

void ZFtpPrivate::applyFtpObject(QSharedPointer<QFtp> ftp)
{
    if (!ftp) return;

    // 断开信号连接
    ftp->disconnect(this);

    // 重新连接信号槽
    connect(ftp.data(), SIGNAL(commandFinished(int,bool)), SLOT(slotCommandFinished(int,bool)));
    connect(ftp.data(), SIGNAL(commandStarted(int)), SLOT(slotCommandStarted(int)));
    connect(ftp.data(), SIGNAL(dataTransferProgress(qint64,qint64)), SLOT(slotDataTransferProgress(qint64,qint64)));
    connect(ftp.data(), SIGNAL(listInfo(QUrlInfo)), SLOT(slotListInfo(QUrlInfo)));
    connect(ftp.data(), SIGNAL(stateChanged(int)), SLOT(slotFtpStateChanged(int)));
    connect(ftp.data(), SIGNAL(stateChanged(int)), SIGNAL(sigFtpStateChanged(int)));
}

void ZFtpPrivate::ensureFtpObjectValid()
{
    if (!m_ftp)
    {
        // 创建QFtp对象
        m_ftp = QSharedPointer<QFtp>(new QFtp);

        // 应用此ftp对象
        applyFtpObject(m_ftp);
    }
}

void ZFtpPrivate::tryStartNextTask()
{
    // Ftp繁忙则直接返回
    if (isFtpBusy()) return;

    // 保证ftp是否有效
    ensureFtpObjectValid();
    Q_ASSERT(m_ftp);

    // 开始新任务
    QMutexLocker locker(&m_task_list_mutex);
    if (m_request_task_list.isEmpty()) return;
    m_current_ftp_task = m_request_task_list.takeFirst();

    // 判空指针
    // 如果请求为空，则开始下一个请求
    if (!m_current_ftp_task.request)
    {
        tryStartNextTask();
        return;
    }

    // 判空指针
    if (m_current_ftp_task.response)
    {
        // 监听Ftp
        m_current_ftp_task.response->listenTo(m_ftp, m_zftp_config);
    }

    // 执行
    int ftp_task_id = m_current_ftp_task.request->doRequest(m_ftp, m_zftp_config);

    // 设置操作ID
    if (m_current_ftp_task.response)
    {
        m_current_ftp_task.response->setFtpTaskID(ftp_task_id);
    }
}

void ZFtpPrivate::addTask(QSharedPointer<ZFtpRequestPrivate> request,
                          QSharedPointer<ZFtpResponsePrivate> response)
{
    // 请求不允许为空，响应可以为空
    if (!request) return;
    if (!response)
    {
        response = QSharedPointer<ZFtpResponsePrivate>(request->createResponse());
    }
    else
    {
        response->setLastErrorString("");
    }

    QMutexLocker locker(&m_task_list_mutex);
    RequestTask rt;
    rt.request = request;
    rt.response = response;
    m_request_task_list.append(rt);

    // 发送任务排队消息
#if 0
    emit response->sigRequestQueued();
#else
    QMetaObject::invokeMethod(response.data(), "sigRequestQueued", Qt::QueuedConnection);
#endif

    // 发送新任务添加的消息，用于实现任务监视
#if 0
    emit sigNewTaskAdded(request, response);
#else
    QMetaObject::invokeMethod(this, "sigNewTaskAdded", Qt::QueuedConnection,
                              Q_ARG(QSharedPointer<ZFtpRequestPrivate>, request),
                              Q_ARG(QSharedPointer<ZFtpResponsePrivate>, response));
#endif
}

bool ZFtpPrivate::isFtpBusy()
{
    return !m_current_ftp_task.request.isNull();
}

void ZFtpPrivate::slotCommandFinished(int id, bool error)
{
    Q_UNUSED(id)
    Q_UNUSED(error)

    m_current_ftp_task.request.clear();
    m_current_ftp_task.response.clear();

    // 开始新任务
    this->tryStartNextTask();
}

void ZFtpPrivate::slotCommandStarted(int id)
{
    Q_UNUSED(id)
}

void ZFtpPrivate::slotDataTransferProgress(qint64 done, qint64 total)
{
    Q_UNUSED(done)
    Q_UNUSED(total)
}

void ZFtpPrivate::slotListInfo(const QUrlInfo &i)
{
    Q_UNUSED(i)
}

void ZFtpPrivate::slotFtpStateChanged(int state)
{
    switch (state)
    {
    case QFtp::LoggedIn:
    {
        break;
    }
    case QFtp::Unconnected:
    {
        // 清除所有任务
        QMutexLocker locker(&m_task_list_mutex);
        m_request_task_list.clear();

        // TODO:自动重连
        if (autoReconnect())
        {

        }

        break;
    }
    default:
    {
        break;
    }
    }

//    case QFtp::HostLookup:
//    {
//        break;
//    }
//    case QFtp::Connecting:
//    {
//        break;
//    }
//    case QFtp::Connected:
//    {
//        break;
//    }
//    case QFtp::Unconnected:
//    {
//        break;
//    }

//    case QFtp::Closing:
//    {
//        break;
    //    }
}

void ZFtpPrivate::slotNewTaskAdded(QSharedPointer<ZFtpRequestPrivate> request,
                                   QSharedPointer<ZFtpResponsePrivate> response)
{
    Q_ASSERT(q_ptr);
    emit q_ptr->sigNewTaskAdded(request->publicObject(), response->publicObject());
}

END_NAMESPACE
